package cn.fintecher.pangolin.service.manage.service;

import cn.fintecher.pangolin.common.enums.BaseStatus;
import cn.fintecher.pangolin.common.enums.StrategyType;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.BeanUtils;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.BaseCase;
import cn.fintecher.pangolin.entity.elastic.Strategy;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.service.manage.elastic.BaseCaseElastic;
import cn.fintecher.pangolin.service.manage.elastic.StrategyElastic;
import cn.fintecher.pangolin.service.manage.repository.CaseInfoRepository;
import cn.fintecher.pangolin.service.manage.request.AddStrategyRequest;
import cn.fintecher.pangolin.service.manage.request.CaseStrategyPreviewRequest;
import cn.fintecher.pangolin.service.manage.request.StrategyPreviewRequest;
import cn.fintecher.pangolin.service.manage.response.StrategyPreviewResponse;
import cn.fintecher.pangolin.service.manage.response.StrategyResponse;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.json.JSONException;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 16:03 2019/8/30
 */

@Service("strategyService")
@Transactional(rollbackFor = Exception.class)
public class StrategyService {
    @Autowired
    private StrategyElastic strategyElastic;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private BaseService baseService;

    @Autowired
    private BaseCaseElastic baseCaseElastic;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    /**
     * 多条件查询分案策略
     */
    public Page<StrategyResponse> findAllStrategy(String name, Pageable pageable) {
        BoolQueryBuilder builder = new BoolQueryBuilder();
        if (StringUtils.isNotBlank(name)) {
            builder.must(QueryBuilders.wildcardQuery("name.keyword", "*" + StringUtils.trim(name) + "*"));
        }
        SortBuilder sortBuilder = SortBuilders.fieldSort("operateTime").unmappedType("date").order(SortOrder.DESC);
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).withPageable(pageable).withSort(sortBuilder).build();
        Page<Strategy> page = strategyElastic.search(searchQuery);
        return page.map(e -> modelMapper.map(e, StrategyResponse.class));
    }

    /**
     * 新增策略
     */
    public void addStrategy(AddStrategyRequest request, String token) throws JSONException {
        UserModel userModel = baseService.getUserByToken(token);
        Strategy strategy = new Strategy();
        BeanUtils.copyPropertiesIgnoreNull(request, strategy);
        strategy.analysisFormula(request.getFormulaJson(), new StringBuilder()); //策略解析
        strategy.setStatus(BaseStatus.ON); //策略状态 默认启用
        strategy.setId(UUID.randomUUID().toString().replaceAll("-", "")); //主键ID
        strategy.process(userModel.getRealName(), ZWDateUtil.getNowDateTime(), true);
        strategyElastic.save(strategy);
    }

    /**
     * 刪除策略
     */
    public void deleteStrategy(String id) {
        strategyElastic.deleteById(id);
    }

    /**
     * 修改策略
     */
    public void modifyStrategy(AddStrategyRequest request, String token) throws JSONException {
        UserModel userModel = baseService.getUserByToken(token);
        Strategy strategy = strategyElastic.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "strategy", "strategy.is.null"));
        strategy.setPrincipalIds(request.getPrincipalIds());
        strategy.setName(request.getName());
        strategy.setStrategyType(request.getStrategyType());
        strategy.setCaseType(request.getCaseType());
        strategy.setPriority(request.getPriority());
        strategy.setType(request.getType());
        strategy.setIsComplex(request.getIsComplex());
        strategy.setModels(request.getModels());
        strategy.setFormulaJson(request.getFormulaJson());
        strategy.analysisFormula(request.getFormulaJson(), new StringBuilder()); //策略解析
        strategy.process(userModel.getRealName(), ZWDateUtil.getNowDateTime(), true);
        strategyElastic.save(strategy);
    }

    /**
     * 获取策略对象
     */
    public Strategy getStrategy(String id) {
        return strategyElastic.findById(id).orElseThrow(() -> new BadRequestException(null, "strategy", "strategy.is.null"));
    }

    /**
     * 策略预览
     */
    public Page<StrategyPreviewResponse> strategyPreview(StrategyPreviewRequest request, Pageable pageable) throws Exception {
        BoolQueryBuilder builder = request.getBuilder();
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).withPageable(pageable).build();
        Page<BaseCase> page = baseCaseElastic.search(searchQuery);
        return page.map(e -> modelMapper.map(e, StrategyPreviewResponse.class));
    }

    /**
     * 案件池策略预览
     */
    public Page<StrategyPreviewResponse> caseStrategyPreview(CaseStrategyPreviewRequest request, Pageable pageable) throws Exception {
        BooleanBuilder builder = request.getBuilder();
        Page<CaseInfo> page = caseInfoRepository.findAll(builder, pageable);
        return page.map(e -> modelMapper.map(e, StrategyPreviewResponse.class));
    }

    /**
     * 复制策略
     */
    public void copyStrategy(String id, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        Strategy strategy = strategyElastic.findById(id).orElseThrow(() -> new BadRequestException(null, "strategy", "strategy.is.null"));
        Strategy result = new Strategy();
        BeanUtils.copyPropertiesIgnoreNull(strategy, result);
        result.setName(strategy.getName() + "-复制");
        result.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        result.process(userModel.getRealName(), ZWDateUtil.getNowDateTime(), true);
        strategyElastic.save(result);
    }
}
